package com.controlier;


import com.domain.Equip_data;
import com.domain.Tcp_public_data;
import com.service.Public_funtion;
import com.service.check_data.Check_equip_Server_data;
import com.service.tcp.ServerChannel_service;
import com.service.tcp.Tcp_doing.KDG_to_Tcp_doing;
import com.service.tcp.Tcp_public_funtion;
import com.utilus.NettyTcpClient;
import com.utilus.NettyTcpServer;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;

import static com.MysqlApplication.equip_list;


@Component
@ChannelHandler.Sharable


public class ServerChannelHandler extends SimpleChannelInboundHandler<Object> {


    @Autowired
    private Public_funtion p;
    @Autowired
    private ServerChannel_service tcp_server;
    @Autowired
    private Tcp_public_funtion tcp_p;
    @Autowired
    KDG_to_Tcp_doing KDGtoTcp_doing;
    @Autowired
    NettyTcpServer nettyTcpServer;
    @Autowired
    NettyTcpClient nettyTcpClient;
    /**
     * 服务器接受的数据跳到此函数内
     */
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception
    {
        //检查基本的格式错误，格式错误踢出去，
        //把接收到的内容转成对象格式
        //没有错误，就执行发来的命令要求
        //吧执行完成的结果发回去
        //打印
        byte[] byte_data=tcp_server.check_tcpdata(msg);
        if(byte_data==null) {
            tcp_p.close_tcp(ctx);
            return;
        }
        Tcp_public_data data=tcp_p.tcp_to_object(byte_data);
        String recive_data= KDGtoTcp_doing.doing(data,ctx);
        p.print_log(recive_data,4);


    }

    /**
     * 客户端连接到服务器上面，完成连接之后跳到此函数
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        //
        //打印
        //检查是否第一次连接，也就是有没有重复连接
        //如果不是第一次连接，就吧连接信息内容写入
        super.channelActive(ctx);
        Equip_data equip=new Equip_data();
        if (tcp_server.check_first_connect(ctx))
        tcp_server.send_welcome_data(ctx);
        equip=tcp_p.Write_info("",ctx);
        p.print_log("ip为"+ equip.getIP() +"连接.",5);

    }

    /**
     * 不活动的通道
     * 连接丢失后执行的方法（client端可据此实现断线重连）
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        //查询该连接在列表中的位置,-1表示没有查到
        //报告
        //删除List中的失效Client
        //关闭连接
        int i =tcp_server.search_object_equiplist(ctx);
        if(i>-1) {
            String report = equip_list.get(i).getIP() + equip_list.get(i).getEquip_name();
            p.print_log(report + "主动断开连接。", 5);
            tcp_server.remove_object_equiplist(i);
        }
        tcp_p.close_tcp(ctx);
    }

    /**
     * 异常处理
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    {

        if (cause instanceof IOException) {
            // 远程主机强迫关闭了一个现有的连接的异常
            ctx.close();
            String report=tcp_p.getIPAddrString(ctx);
            p.print_log(report+"发送异常信息，服务器与设备被迫断开。",5);
        } else {
            try{
                super.exceptionCaught(ctx, cause);
            } catch (Exception e) {
                e.printStackTrace();
            }
            p.print_log("其他异常。",5);
        }
//        channelInactive(ctx);
    }
    /**fireChannelRegistered
     * 心跳机制，超时处理
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        String socketString = ctx.channel().remoteAddress().toString();
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                System.out.println("Client: " + socketString + " READER_IDLE 读超时");
                channelInactive(ctx);//断开
            } else if (event.state() == IdleState.WRITER_IDLE) {
                System.out.println("Client: " + socketString + " WRITER_IDLE 写超时");
                channelInactive(ctx);
            } else if (event.state() == IdleState.ALL_IDLE) {
                System.out.println("Client: " + socketString + " ALL_IDLE 总超时");
                channelInactive(ctx);
            }
        }
    }


    public  void tcp_init( ) throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run()
            {
                ChannelFuture start = nettyTcpServer.start();
                nettyTcpClient.connect();
                //服务端管道关闭的监听器并同步阻塞,直到channel关闭,线程才会往下执行,结束进程
                start.channel().closeFuture().syncUninterruptibly();
            }
        }).start();
    }
}
